package com.peak.spring.boot.core.web;

import java.util.List;

import javax.servlet.http.HttpServletRequest;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;

import com.peak.spring.boot.api.constant.ErrorMessage;
import com.peak.spring.boot.api.constant.SuccessMessage;
import com.peak.spring.boot.api.entity.Identity;
import com.peak.spring.boot.api.manager.BaseManager;
import com.peak.spring.boot.api.repository.FilterParam;
import com.peak.spring.boot.api.web.IdVo;
import com.peak.spring.boot.api.web.JsonMessage;
import com.peak.spring.boot.api.web.JsonPage;
import com.peak.spring.boot.builder.repository.FilterParamBuilder;
import com.peak.spring.boot.builder.web.JsonBuilder;
import com.peak.spring.boot.core.exception.ProjectException;
import com.peak.spring.boot.tools.Converts;
import com.peak.spring.boot.tools.Emptys;
import com.peak.spring.boot.tools.Reflections;
import com.peak.spring.boot.tools.Servlets;

/**
 * 公共Controller，其他的Controller继承该类，实现了list, get, save, delete方法
 * 
 * @author Haley Gao
 *
 * @param <T>
 * @param <V>
 */
public abstract class BaseController<T extends Identity, V extends IdVo> {

	@Autowired
	protected BaseManager<T> baseManager;

	protected Class<V> voClass;

	protected Class<T> poClass;

	@SuppressWarnings("unchecked")
	public Class<V> getVoClass() {
		if (this.voClass == null) {
			this.voClass = (Class<V>) Reflections.getClassGenricType(this.getClass(), 1);
		}
		return voClass;
	}

	public Class<T> getPoClass() {
		if (poClass == null) {
			poClass = Reflections.getClassGenricType(this.getClass());
		}
		return poClass;
	}

	@PostMapping("/list")
	public JsonPage list(HttpServletRequest request) {
		FilterParamBuilder builder = FilterParamBuilder.create().parseRequest(request);
		List<FilterParam> filterParams = builder.build();
		PageRequest pageRequest = builder.pageRequest();
		beforeList(request, filterParams, pageRequest);
		Page<T> page = baseManager.findPage(filterParams, pageRequest);
		JsonPage json = JsonBuilder.page().success().page(page).convert(getVoClass()).build();
		json = afterList(json);
		return json;
	}

	@PostMapping("/get/{id}")
	public JsonMessage get(@PathVariable("id") Number id) {
		T entity = baseManager.findOne(id);
		if (entity == null) {
			throw new ProjectException(ErrorMessage.DATA_NOT_FOUND);
		}
		JsonMessage json = JsonBuilder.message().success().content(entity).convert(getVoClass()).build();
		json = afterGet(json);
		return json;
	}

	@PostMapping("/save")
	public JsonMessage save(HttpServletRequest request) {
		T entity = null;
		String id = request.getParameter("id");
		if (Emptys.isEmpty(id)) {
			entity = Servlets.bind(request, getPoClass());
		} else {
			entity = baseManager.findOne(Converts.toLong(id));
			if (entity != null) {
				entity = Servlets.bind(request, entity);
			}
		}
		entity = beforeSave(request, entity);
		baseManager.save(entity);
		JsonMessage resp = afterSave(request, entity);
		if (resp == null) {
			resp = JsonBuilder.message().success().content(SuccessMessage.SUCCESS).build();
		}
		return resp;
	}

	@PostMapping("/delete/{id}")
	public JsonMessage delete(@PathVariable("id") Number id) {
		T entity = baseManager.findOne(id);
		if (entity == null) {
			throw new ProjectException(ErrorMessage.DATA_NOT_FOUND);
		}
		beforeDelete(entity);
		baseManager.delete(entity);
		afterDelete(entity);
		return JsonBuilder.message().success().content(SuccessMessage.SUCCESS).build();
	}

	protected JsonPage afterList(JsonPage json) {
		return json;
	}

	protected void beforeList(HttpServletRequest request, List<FilterParam> filterParams, PageRequest pageRequest) {
	}
	
	protected JsonMessage afterGet(JsonMessage json) {
		return json;
	}

	protected void beforeDelete(T entity) {
	}

	protected void afterDelete(T entity) {
	}

	protected JsonMessage afterSave(HttpServletRequest request, T entity) {
		return JsonBuilder.message().success().content(SuccessMessage.SUCCESS).build();
	}

	protected T beforeSave(HttpServletRequest request, T entity) {
		return entity;
	}

}
